<template><div><p>本文档最新版为 <a href="https://learnku.com/docs/laravel/10.x" target="_blank" rel="noopener noreferrer">10.x</a>，旧版本可能放弃维护，推荐阅读最新版！</p>
<h2 id="缓存" tabindex="-1"><a class="header-anchor" href="#缓存"><span>缓存</span></a></h2>
<ul>
<li><a href="#introduction">简介</a></li>
<li><a href="#configuration">配置</a>
<ul>
<li><a href="#driver-prerequisites">驱动器先决条件</a></li>
</ul>
</li>
<li><a href="#cache-usage">缓存使用</a>
<ul>
<li><a href="#obtaining-a-cache-instance">获取缓存实例</a></li>
<li><a href="#retrieving-items-from-the-cache">从缓存中检索项目</a></li>
<li><a href="#storing-items-in-the-cache">在缓存中存储项目</a></li>
<li><a href="#removing-items-from-the-cache">从缓存中移除项目</a></li>
<li><a href="#the-cache-helper">缓存辅助函数</a></li>
</ul>
</li>
<li><a href="#atomic-locks">原子锁</a>
<ul>
<li><a href="#managing-locks">管理锁</a></li>
<li><a href="#managing-locks-across-processes">跨进程管理锁</a></li>
</ul>
</li>
<li><a href="#adding-custom-cache-drivers">添加自定义缓存驱动器</a>
<ul>
<li><a href="#writing-the-driver">编写驱动器</a></li>
<li><a href="#registering-the-driver">注册驱动器</a></li>
</ul>
</li>
<li><a href="#events">事件</a></li>
</ul>
<h2 id="简介" tabindex="-1"><a class="header-anchor" href="#简介"><span>简介</span></a></h2>
<p>您的应用程序执行的一些数据检索或处理任务可能非常消耗CPU资源，或者需要几秒钟才能完成。在这种情况下，通常会将检索到的数据临时缓存一段时间，以便在后续对相同数据的请求中快速检索。缓存的数据通常存储在非常快速的数据存储中，如<a href="https://memcached.org/" target="_blank" rel="noopener noreferrer">Memcached</a>或<a href="https://redis.io/" target="_blank" rel="noopener noreferrer">Redis</a>。</p>
<p>值得庆幸的是，Laravel为各种缓存后端提供了一个表达性强、统一的API，使您能够利用它们超高速的数据检索能力，加速您的Web应用程序。</p>
<h2 id="配置" tabindex="-1"><a class="header-anchor" href="#配置"><span>配置</span></a></h2>
<p>您的应用程序缓存配置文件位于<code v-pre>config/cache.php</code>。在这个文件中，您可以指定希望在整个应用程序中默认使用的缓存存储。Laravel开箱即支持流行的缓存后端，如<a href="https://memcached.org/" target="_blank" rel="noopener noreferrer">Memcached</a>、<a href="https://redis.io/" target="_blank" rel="noopener noreferrer">Redis</a>、<a href="https://aws.amazon.com/dynamodb" target="_blank" rel="noopener noreferrer">DynamoDB</a>以及关系型数据库。此外，还提供了基于文件的缓存驱动器，同时<code v-pre>array</code>和<code v-pre>null</code>缓存驱动器为您的自动化测试提供了便捷的缓存后端。</p>
<p>缓存配置文件中还包含了许多其他选项，您可以查阅并根据需要调整。默认情况下，Laravel配置为使用<code v-pre>database</code>缓存驱动器，该驱动器会将序列化的缓存对象存储在应用程序的数据库中。</p>
<h3 id="缓存驱动的先决条件" tabindex="-1"><a class="header-anchor" href="#缓存驱动的先决条件"><span>缓存驱动的先决条件</span></a></h3>
<h4 id="数据库驱动" tabindex="-1"><a class="header-anchor" href="#数据库驱动"><span>数据库驱动</span></a></h4>
<p>当使用<code v-pre>database</code>缓存驱动时，您需要一个数据库表来存储缓存数据。通常，这个表会在Laravel的默认数据库迁移<code v-pre>0001_01_01_000001_create_cache_table.php</code>中自动生成；但如果您应用中没有这个迁移，可以使用<code v-pre>make:cache-table</code> Artisan命令来创建：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">php artisan make:cache-table</span>
<span class="line"></span>
<span class="line">php artisan migrate</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="memcached" tabindex="-1"><a class="header-anchor" href="#memcached"><span>Memcached</span></a></h4>
<p>使用Memcached驱动要求安装<a href="https://pecl.php.net/package/memcached" target="_blank" rel="noopener noreferrer">Memcached PECL扩展</a>。您可以在<code v-pre>config/cache.php</code>配置文件中列出所有的Memcached服务器。此文件已包含一个<code v-pre>memcached.servers</code>条目作为起点：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token string single-quoted-string">'memcached'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"></span>
<span class="line">    <span class="token string single-quoted-string">'servers'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token punctuation">[</span></span>
<span class="line">            <span class="token string single-quoted-string">'host'</span> <span class="token operator">=></span> <span class="token function">env</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'MEMCACHED_HOST'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'127.0.0.1'</span><span class="token punctuation">)</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token string single-quoted-string">'port'</span> <span class="token operator">=></span> <span class="token function">env</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'MEMCACHED_PORT'</span><span class="token punctuation">,</span> <span class="token number">11211</span><span class="token punctuation">)</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token string single-quoted-string">'weight'</span> <span class="token operator">=></span> <span class="token number">100</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如有需要，您可以将<code v-pre>host</code>选项设置为UNIX套接字路径。就像，<code v-pre>port</code>选项应设为<code v-pre>0</code>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token string single-quoted-string">'memcached'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"></span>
<span class="line">    <span class="token string single-quoted-string">'servers'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token punctuation">[</span></span>
<span class="line">            <span class="token string single-quoted-string">'host'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'/var/run/memcached/memcached.sock'</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token string single-quoted-string">'port'</span> <span class="token operator">=></span> <span class="token number">0</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token string single-quoted-string">'weight'</span> <span class="token operator">=></span> <span class="token number">100</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="redis" tabindex="-1"><a class="header-anchor" href="#redis"><span>Redis</span></a></h4>
<p>在Laravel中使用Redis缓存之前，您需要通过PECL安装PhpRedis PHP扩展，或者通过Composer安装<code v-pre>predis/predis</code>包（~2.0版本）。<a href="https://learnku.com/docs/laravel/11.x/sailmd/16731" target="_blank" rel="noopener noreferrer">Laravel Sail</a> 已包含此扩展。此外，诸如 <a href="https://forge.laravel.com/" target="_blank" rel="noopener noreferrer">Laravel Forge</a> 和 <a href="https://vapor.laravel.com/" target="_blank" rel="noopener noreferrer">Laravel Vapor</a> 这样的官方Laravel部署平台，默认已安装PhpRedis扩展。</p>
<p>有关配置 Redis 的更多信息，请查阅其 <a href="https://learnku.com/docs/laravel/11.x/redismd#configuration" target="_blank" rel="noopener noreferrer">Laravel 文档页面</a>。</p>
<h4 id="dynamodb" tabindex="-1"><a class="header-anchor" href="#dynamodb"><span>DynamoDB</span></a></h4>
<p>在使用 <a href="https://aws.amazon.com/dynamodb" target="_blank" rel="noopener noreferrer">DynamoDB</a> 缓存驱动程序之前，你必须创建一个 DynamoDB 表来存储所有缓存的数据。通常，此表应命名为 <code v-pre>cache</code>。但是，你应该根据 <code v-pre>cache</code> 配置文件中的 <code v-pre>stores.dynamodb.table</code> 配置值来命名表。表名也可以通过 <code v-pre>DYNAMODB_CACHE_TABLE</code> 环境变量设置。</p>
<p>此表还应有一个与应用程序的 <code v-pre>cache</code> 配置文件中的 <code v-pre>stores.dynamodb.attributes.key</code> 配置项值相对应的字符串分区键。默认情况下，分区键应命名为 <code v-pre>key</code>。</p>
<p>接下来，安装 AWS SDK，以便你的 Laravel 应用程序能够与 DynamoDB 通信：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line"><span class="token function">composer</span> require aws/aws-sdk-php</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>此外，你应确保为 DynamoDB 缓存存储的配置选项提供了值。通常，这些选项，如 <code v-pre>AWS_ACCESS_KEY_ID</code> 和 <code v-pre>AWS_SECRET_ACCESS_KEY</code>，应在应用程序的 <code v-pre>.env</code> 配置文件中定义：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token string single-quoted-string">'dynamodb'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'driver'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'dynamodb'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'key'</span> <span class="token operator">=></span> <span class="token function">env</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'AWS_ACCESS_KEY_ID'</span><span class="token punctuation">)</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'secret'</span> <span class="token operator">=></span> <span class="token function">env</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'AWS_SECRET_ACCESS_KEY'</span><span class="token punctuation">)</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'region'</span> <span class="token operator">=></span> <span class="token function">env</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'AWS_DEFAULT_REGION'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'us-east-1'</span><span class="token punctuation">)</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'table'</span> <span class="token operator">=></span> <span class="token function">env</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'DYNAMODB_CACHE_TABLE'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'cache'</span><span class="token punctuation">)</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'endpoint'</span> <span class="token operator">=></span> <span class="token function">env</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'DYNAMODB_ENDPOINT'</span><span class="token punctuation">)</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="缓存使用" tabindex="-1"><a class="header-anchor" href="#缓存使用"><span>缓存使用</span></a></h2>
<h3 id="获取缓存实例" tabindex="-1"><a class="header-anchor" href="#获取缓存实例"><span>获取缓存实例</span></a></h3>
<p>要获取缓存存储实例，你可以使用 <code v-pre>Cache</code> facade，这是我们在本文档中将使用的。<code v-pre>Cache</code> facade 为 Laravel 缓存契约的底层实现提供了便利、简洁的访问：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Controllers</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Cache</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">UserController</span> <span class="token keyword">extends</span> <span class="token class-name">Controller</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 显示应用程序所有用户的列表。</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">index</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">array</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token variable">$value</span> <span class="token operator">=</span> <span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">            <span class="token comment">// ...</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="访问多个缓存存储" tabindex="-1"><a class="header-anchor" href="#访问多个缓存存储"><span>访问多个缓存存储</span></a></h4>
<p>使用 <code v-pre>Cache</code> facade，你可以通过 <code v-pre>store</code> 方法访问各种缓存存储。传递给 <code v-pre>store</code> 方法的键应对应于你的 <code v-pre>cache</code> 配置文件中的 <code v-pre>stores</code> 配置数组中列出的存储之一：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$value</span> <span class="token operator">=</span> <span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">store</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'file'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'foo'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">store</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'redis'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'bar'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'baz'</span><span class="token punctuation">,</span> <span class="token number">600</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 10 分钟</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="从缓存中检索项目" tabindex="-1"><a class="header-anchor" href="#从缓存中检索项目"><span>从缓存中检索项目</span></a></h3>
<p><code v-pre>Cache</code> facade 的 <code v-pre>get</code> 方法用于从缓存中检索项目。如果缓存中不存在该项目，将返回 <code v-pre>null</code>。如果您愿意，可以向 <code v-pre>get</code> 方法传递第二个参数，指定如果项目不存在希望返回的默认值：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$value</span> <span class="token operator">=</span> <span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$value</span> <span class="token operator">=</span> <span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'default'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>你甚至可以传递一个闭包作为默认值。如果指定的项目不存在于缓存中，则会返回闭包的结果。传递闭包允许你推迟从数据库或其他外部服务检索默认值：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$value</span> <span class="token operator">=</span> <span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token class-name static-context">DB</span><span class="token operator">::</span><span class="token function">table</span><span class="token punctuation">(</span><span class="token comment">/* ... */</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="检查项目是否存在" tabindex="-1"><a class="header-anchor" href="#检查项目是否存在"><span>检查项目是否存在</span></a></h4>
<p><code v-pre>has</code> 方法可用于确定缓存中是否存在某个项目。如果该项目存在但其值为 <code v-pre>null</code>，此方法也将返回 <code v-pre>false</code>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">has</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="递增-递减值" tabindex="-1"><a class="header-anchor" href="#递增-递减值"><span>递增 / 递减值</span></a></h4>
<p><code v-pre>increment</code> 和 <code v-pre>decrement</code> 方法可用于调整缓存中整数项目的值。这两个方法都接受一个可选的第二个参数，指示增加或减少项目值的数量：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token comment">// 如果值不存在，则初始化该值..</span></span>
<span class="line"><span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">addHours</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 增加或减少值...</span></span>
<span class="line"><span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">increment</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">increment</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">,</span> <span class="token variable">$amount</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">decrement</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">decrement</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">,</span> <span class="token variable">$amount</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="检索和存储" tabindex="-1"><a class="header-anchor" href="#检索和存储"><span>检索和存储</span></a></h4>
<p>有时你可能希望从缓存中检索一个项目，但如果请求的项目不存在，也会存储一个默认值。例如，你可能希望从缓存中检索所有用户，如果他们不存在，则从数据库中检索他们并将其添加到缓存中。你可以使用 <code v-pre>Cache::remember</code> 方法来做这件事：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$value</span> <span class="token operator">=</span> <span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">remember</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'users'</span><span class="token punctuation">,</span> <span class="token variable">$seconds</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token class-name static-context">DB</span><span class="token operator">::</span><span class="token function">table</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'users'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果项目不存在于缓存中，传递给 <code v-pre>remember</code> 方法的闭包将被执行，其结果将被放入缓存中。</p>
<p>你可以使用 <code v-pre>rememberForever</code> 方法从缓存中检索一个项目，或者如果它不存在，则永久存储它：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$value</span> <span class="token operator">=</span> <span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">rememberForever</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'users'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token class-name static-context">DB</span><span class="token operator">::</span><span class="token function">table</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'users'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="检索和删除" tabindex="-1"><a class="header-anchor" href="#检索和删除"><span>检索和删除</span></a></h4>
<p>如果你需要从缓存中检索一个项目，然后删除该项目，您可以使用 <code v-pre>pull</code> 方法。与 <code v-pre>get</code> 方法一样，如果缓存中不存在该项目，将返回 <code v-pre>null</code>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$value</span> <span class="token operator">=</span> <span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">pull</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$value</span> <span class="token operator">=</span> <span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">pull</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'default'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="存储项目到缓存中" tabindex="-1"><a class="header-anchor" href="#存储项目到缓存中"><span>存储项目到缓存中</span></a></h3>
<p>你可以使用 <code v-pre>Cache</code> facade 上的 <code v-pre>put</code> 方法将项目存储到缓存中：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'value'</span><span class="token punctuation">,</span> <span class="token variable">$seconds</span> <span class="token operator">=</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>如果未向 <code v-pre>put</code> 方法传递存储时间，则该项目将被无限期存储：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'value'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>除了将秒数作为整数传递之外，你还可以传递一个代表缓存项所需过期时间的 <code v-pre>DateTime</code> 实例：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'value'</span><span class="token punctuation">,</span> <span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">addMinutes</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="如果不存在则存储" tabindex="-1"><a class="header-anchor" href="#如果不存在则存储"><span>如果不存在则存储</span></a></h4>
<p><code v-pre>add</code> 方法只有在缓存存储中不存在时才会添加项目。如果项目实际添加到缓存中，则该方法将返回 <code v-pre>true</code>。否则，该方法将返回 <code v-pre>false</code>。<code v-pre>add</code> 方法是一个原子操作：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'value'</span><span class="token punctuation">,</span> <span class="token variable">$seconds</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="永久存储项目" tabindex="-1"><a class="header-anchor" href="#永久存储项目"><span>永久存储项目</span></a></h4>
<p><code v-pre>forever</code> 方法可用于永久存储缓存中的项目。由于这些项目不会过期，它们必须使用 <code v-pre>forget</code> 方法手动从缓存中移除：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">forever</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'value'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><blockquote>
<p><strong>注意</strong><br>
如果你使用的是 Memcached 驱动程序，当缓存达到大小限制时，存储的「永久」项目可能会被移除。</p>
</blockquote>
<h3 id="从缓存中移除项目" tabindex="-1"><a class="header-anchor" href="#从缓存中移除项目"><span>从缓存中移除项目</span></a></h3>
<p>你可以使用 <code v-pre>forget</code> 方法从缓存中移除项目：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">forget</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>你也可以通过提供零或负数的过期秒数来移除项目：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'value'</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'value'</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>你可以使用 <code v-pre>flush</code> 方法清除整个缓存：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">flush</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><blockquote>
<p><strong>注意</strong><br>
清除缓存不会考虑你配置的缓存「前缀」，并且会从缓存中删除所有条目。当清除一个被其他应用程序共享的缓存时，请谨慎考虑。</p>
</blockquote>
<h3 id="缓存助手函数" tabindex="-1"><a class="header-anchor" href="#缓存助手函数"><span>缓存助手函数</span></a></h3>
<p>除了使用 <code v-pre>Cache</code> facade，你还可以使用全局 <code v-pre>cache</code> 函数通过缓存检索和存储数据。当调用 <code v-pre>cache</code> 函数时，且带有单个字符串参数，它将返回给定键的值：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$value</span> <span class="token operator">=</span> <span class="token function">cache</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>如果向函数提供键值对数组和过期时间，则它将在指定的时长内存储缓存中的值：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token function">cache</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'key'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'value'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token variable">$seconds</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token function">cache</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'key'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'value'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">addMinutes</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>当不带任何参数调用<code v-pre>cache</code> 函数时，它返回一个 <code v-pre>Illuminate\Contracts\Cache\Factory</code> 实现的实例，允许你调用其他缓存方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token function">cache</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">remember</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'users'</span><span class="token punctuation">,</span> <span class="token variable">$seconds</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token class-name static-context">DB</span><span class="token operator">::</span><span class="token function">table</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'users'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>注意</strong><br>
当测试全局 <code v-pre>cache</code> 函数的调用时，你可以使用 <code v-pre>Cache::shouldReceive</code> 方法，就像在 <a href="https://learnku.com/docs/laravel/11.x/mockingmd#mocking-facades" target="_blank" rel="noopener noreferrer">测试 facade</a> 时一样。</p>
</blockquote>
<h2 id="原子锁" tabindex="-1"><a class="header-anchor" href="#原子锁"><span>原子锁</span></a></h2>
<blockquote>
<p><strong>注意</strong><br>
要使用此功能，你的应用程序必须使用 <code v-pre>memcached</code>、<code v-pre>redis</code>、<code v-pre>dynamodb</code>、<code v-pre>database</code>、<code v-pre>file</code> 或 <code v-pre>array</code> 缓存驱动程序作为应用程序的默认缓存驱动程序。此外，所有服务器必须与相同的中心缓存服务器通信。</p>
</blockquote>
<h3 id="管理锁" tabindex="-1"><a class="header-anchor" href="#管理锁"><span>管理锁</span></a></h3>
<p>原子锁允许操作分布式锁而不用担心竞争条件。例如，<a href="https://forge.laravel.com/" target="_blank" rel="noopener noreferrer">Laravel Forge</a> 使用原子锁确保一次只在服务器上执行一个远程任务。你可以使用 <code v-pre>Cache::lock</code> 方法来创建和管理锁：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Cache</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$lock</span> <span class="token operator">=</span> <span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">lock</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'foo'</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$lock</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 锁定 10 秒...</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$lock</span><span class="token operator">-></span><span class="token function">release</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code v-pre>get</code> 方法还接受一个闭包。一旦执行了闭包，Laravel 将自动释放锁：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">lock</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'foo'</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 锁定 10 秒并自动释放...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果你请求时锁不可用，你可以指示 Laravel 等待指定的秒数。如果在指定的时间限制内无法获得锁，将抛出 <code v-pre>Illuminate\Contracts\Cache\LockTimeoutException</code>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Contracts<span class="token punctuation">\</span>Cache<span class="token punctuation">\</span>LockTimeoutException</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$lock</span> <span class="token operator">=</span> <span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">lock</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'foo'</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">try</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$lock</span><span class="token operator">-></span><span class="token function">block</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token comment">// 等待最多 5 秒后获得锁...</span></span>
<span class="line"><span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">LockTimeoutException</span> <span class="token variable">$e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 无法获得锁...</span></span>
<span class="line"><span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$lock</span><span class="token operator">?-></span><span class="token function">release</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>可以通过将闭包传递给 <code v-pre>block</code> 方法，简化上面的示例。当将闭包传递给这个方法时，Laravel 将尝试在指定的秒数内获得锁，并在执行闭包后自动释放锁：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">lock</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'foo'</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">block</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 最多等待5秒后获得锁...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="跨进程管理锁" tabindex="-1"><a class="header-anchor" href="#跨进程管理锁"><span>跨进程管理锁</span></a></h3>
<p>有时，你可能希望在一个进程中获得锁，并在另一个进程中释放它。例如，你可能在一个 Web 请求中获得锁，并希望在由该请求触发的队列任务结束时释放锁。在这种情况下，你应该将锁的作用域「owner token」传递给队列任务，以便任务可以使用给定的令牌重新实例化锁。</p>
<p>在下面的示例中，如果成功获得锁，我们将调度一个队列任务。此外，我们将通过锁的 <code v-pre>owner</code> 方法将锁的所有者令牌传递给队列任务：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$podcast</span> <span class="token operator">=</span> <span class="token class-name static-context">Podcast</span><span class="token operator">::</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token variable">$id</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$lock</span> <span class="token operator">=</span> <span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">lock</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'processing'</span><span class="token punctuation">,</span> <span class="token number">120</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$lock</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token class-name static-context">ProcessPodcast</span><span class="token operator">::</span><span class="token function">dispatch</span><span class="token punctuation">(</span><span class="token variable">$podcast</span><span class="token punctuation">,</span> <span class="token variable">$lock</span><span class="token operator">-></span><span class="token function">owner</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在我们应用程序的 <code v-pre>ProcessPodcast</code> 任务中，我们可以使用所有者令牌恢复和释放锁：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">restoreLock</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'processing'</span><span class="token punctuation">,</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">owner</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">release</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>如果你希望释放锁而不考虑其当前所有者，你可以使用 <code v-pre>forceRelease</code> 方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">lock</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'processing'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">forceRelease</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h2 id="添加自定义缓存驱动" tabindex="-1"><a class="header-anchor" href="#添加自定义缓存驱动"><span>添加自定义缓存驱动</span></a></h2>
<h3 id="编写驱动" tabindex="-1"><a class="header-anchor" href="#编写驱动"><span>编写驱动</span></a></h3>
<p>要创建我们的自定义缓存驱动，我们首先需要实现 <code v-pre>Illuminate\Contracts\Cache\Store</code> <a href="https://learnku.com/docs/laravel/11.x/contractsmd" target="_blank" rel="noopener noreferrer">Contract</a>。因此，一个 MongoDB 缓存实现可能看起来像这样：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Extensions</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Contracts<span class="token punctuation">\</span>Cache<span class="token punctuation">\</span>Store</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">MongoStore</span> <span class="token keyword">implements</span> <span class="token class-name">Store</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">get</span><span class="token punctuation">(</span><span class="token variable">$key</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">many</span><span class="token punctuation">(</span><span class="token keyword type-hint">array</span> <span class="token variable">$keys</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">put</span><span class="token punctuation">(</span><span class="token variable">$key</span><span class="token punctuation">,</span> <span class="token variable">$value</span><span class="token punctuation">,</span> <span class="token variable">$seconds</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">putMany</span><span class="token punctuation">(</span><span class="token keyword type-hint">array</span> <span class="token variable">$values</span><span class="token punctuation">,</span> <span class="token variable">$seconds</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">increment</span><span class="token punctuation">(</span><span class="token variable">$key</span><span class="token punctuation">,</span> <span class="token variable">$value</span> <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">decrement</span><span class="token punctuation">(</span><span class="token variable">$key</span><span class="token punctuation">,</span> <span class="token variable">$value</span> <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">forever</span><span class="token punctuation">(</span><span class="token variable">$key</span><span class="token punctuation">,</span> <span class="token variable">$value</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">forget</span><span class="token punctuation">(</span><span class="token variable">$key</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">flush</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">getPrefix</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>我们只需要使用 MongoDB 连接实现每个方法。要查看如何实现每个方法的示例，可以看一下 <a href="https://github.com/laravel/framework" target="_blank" rel="noopener noreferrer">Laravel 框架源码</a> 中的 <code v-pre>Illuminate\Cache\MemcachedStore</code>。完成实现后，我们可以通过调用 <code v-pre>Cache</code> facade 的 <code v-pre>extend</code> 方法完成我们的自定义驱动注册：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">extend</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'mongo'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Application</span> <span class="token variable">$app</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">repository</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">MongoStore</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>技巧</strong><br>
如果你想知道在哪里放置你的自定义缓存驱动代码，你可以在 <code v-pre>app</code> 目录中创建一个 <code v-pre>Extensions</code> 命名空间。但是，请记住，Laravel 没有严格的应用程序结构，你可以根据自己的喜好自由组织你的应用程序。</p>
</blockquote>
<h3 id="注册驱动" tabindex="-1"><a class="header-anchor" href="#注册驱动"><span>注册驱动</span></a></h3>
<p>要在 Laravel 中注册自定义缓存驱动程序，我们将使用 <code v-pre>Cache</code> facade 上的 <code v-pre>extend</code> 方法。由于其他服务提供者可能会尝试在其 <code v-pre>boot</code> 方法中读取缓存的值，我们将在 <code v-pre>booting</code> 回调中注册我们的自定义驱动程序。通过使用 <code v-pre>booting</code> 回调，我们可以确保在我们应用程序的服务提供者的 <code v-pre>boot</code> 方法调用之前，且在所有服务提供者的 <code v-pre>register</code> 方法调用之后，就注册自定义驱动程序。我们将在应用程序的 <code v-pre>App\Providers\AppServiceProvider</code> 类的 <code v-pre>register</code> 方法中注册我们的 <code v-pre>booting</code> 回调：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Providers</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Extensions<span class="token punctuation">\</span>MongoStore</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Contracts<span class="token punctuation">\</span>Foundation<span class="token punctuation">\</span>Application</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Cache</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>ServiceProvider</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">AppServiceProvider</span> <span class="token keyword">extends</span> <span class="token class-name">ServiceProvider</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 注册任何应用程序服务</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">register</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">app</span><span class="token operator">-></span><span class="token function">booting</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">             <span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">extend</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'mongo'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Application</span> <span class="token variable">$app</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">                 <span class="token keyword">return</span> <span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">repository</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">MongoStore</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">             <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">         <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 引导任何应用程序服务</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">boot</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// ...</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>传递给 <code v-pre>extend</code> 方法的第一个参数是驱动程序的名称。这将对应于 <code v-pre>config/cache.php</code> 配置文件中的 <code v-pre>driver</code> 选项。第二个参数是一个闭包，应该返回一个 <code v-pre>Illuminate\Cache\Repository</code> 实例。这个闭包将被传递一个 <code v-pre>$app</code> 实例，这是 <a href="https://learnku.com/docs/laravel/11.x/containermd" target="_blank" rel="noopener noreferrer">服务容器</a> 的一个实例。</p>
<p>注册扩展后，更新应用程序的 <code v-pre>config/cache.php</code> 配置文件中的 <code v-pre>CACHE_STORE</code> 环境变量或 <code v-pre>default</code> 选项为扩展的名称。</p>
<h2 id="事件" tabindex="-1"><a class="header-anchor" href="#事件"><span>事件</span></a></h2>
<p>你可以监听由缓存分发的各种<a href="https://learnku.com/docs/laravel/11.x/eventsmd" target="_blank" rel="noopener noreferrer">事件</a>，以便在每个缓存操作上执行代码：</p>
<table>
<thead>
<tr>
<th>事件名称</th>
</tr>
</thead>
<tbody>
<tr>
<td><code v-pre>Illuminate\Cache\Events\CacheHit</code></td>
</tr>
<tr>
<td><code v-pre>Illuminate\Cache\Events\CacheMissed</code></td>
</tr>
<tr>
<td><code v-pre>Illuminate\Cache\Events\KeyForgotten</code></td>
</tr>
<tr>
<td><code v-pre>Illuminate\Cache\Events\KeyWritten</code></td>
</tr>
</tbody>
</table>
<p>为提升性能，你可以在应用程序的 <code v-pre>config/cache.php</code> 配置文件中，为特定缓存存储设置 <code v-pre>events</code> 配置项为 <code v-pre>false</code> ，从而禁用缓存事件：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token string single-quoted-string">'database'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'driver'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'database'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line">    <span class="token string single-quoted-string">'events'</span> <span class="token operator">=></span> <span class="token constant boolean">false</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p>本译文仅用于学习和交流目的，转载请务必注明文章译者、出处、和本文链接<br>
我们的翻译工作遵照 <a href="https://learnku.com/docs/guide/cc4.0/6589" target="_blank" rel="noopener noreferrer">CC 协议</a>，如果我们的工作有侵犯到您的权益，请及时联系我们。</p>
</blockquote>
<hr>
<blockquote>
<p>原文地址：<a href="https://learnku.com/docs/laravel/11.x/cachemd/16673" target="_blank" rel="noopener noreferrer">https://learnku.com/docs/laravel/11.x/ca...</a></p>
<p>译文地址：<a href="https://learnku.com/docs/laravel/11.x/cachemd/16673" target="_blank" rel="noopener noreferrer">https://learnku.com/docs/laravel/11.x/ca...</a></p>
</blockquote>
</div></template>


